package com.zhuanzhuan.hero.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.bj58.youpin.common.utils.json.JsonUtils;
import com.bj58.zhuanzhuan.zzentry.common.service.entity.ServiceHeaderEntity;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zhuanzhuan.hero.biz.common.entity.risk.control.request.RecycleShareRiskControlRequest;
import com.zhuanzhuan.hero.biz.common.entity.risk.control.request.UserBaseInfoRiskControlRequest;
import com.zhuanzhuan.hero.biz.common.entity.risk.control.request.UserCoverRiskControlRequest;
import com.zhuanzhuan.hero.biz.common.entity.risk.control.request.UserProfileRiskControlRequest;
import com.zhuanzhuan.hero.biz.common.entity.risk.control.response.RiskControlResult;
import com.zhuanzhuan.hero.biz.common.enums.RiskControlResultType;
import com.zhuanzhuan.hero.biz.common.util.WxWarnTemplateUtil;
import com.zhuanzhuan.hero.member.response.MemberDTO;
import com.zhuanzhuan.hero.recycle.order.vo.UserCenterSellAndRecycleCountVO;
import com.zhuanzhuan.hero.search.module.dto.UserRegisterDTO;
import com.zhuanzhuan.hero.user.config.ThreadPoolConfiguration;
import com.zhuanzhuan.hero.user.consts.Consts;
import com.zhuanzhuan.hero.user.consts.NumConsts;
import com.zhuanzhuan.hero.user.consts.UserInfoFieldConsts;
import com.zhuanzhuan.hero.user.converter.LabelConverter;
import com.zhuanzhuan.hero.user.converter.UserInfoConvert;
import com.zhuanzhuan.hero.user.dto.*;
import com.zhuanzhuan.hero.user.entity.*;
import com.zhuanzhuan.hero.user.enums.*;
import com.zhuanzhuan.hero.user.exception.BusinessException;
import com.zhuanzhuan.hero.user.helper.*;
import com.zhuanzhuan.hero.user.mapper.HeroUserInfoMapper;
import com.zhuanzhuan.hero.user.mq.dto.BaseUserMsg;
import com.zhuanzhuan.hero.user.mq.dto.UserBaseInfoMsg;
import com.zhuanzhuan.hero.user.mq.producer.HeroUserProducer;
import com.zhuanzhuan.hero.user.pojo.bo.*;
import com.zhuanzhuan.hero.user.pojo.po.LabelInfoPO;
import com.zhuanzhuan.hero.user.pojo.po.UserPO;
import com.zhuanzhuan.hero.user.service.*;
import com.zhuanzhuan.hero.user.util.Assert;
import com.zhuanzhuan.hero.user.util.AsyncUtil;
import com.zhuanzhuan.hero.user.util.StringUtil;
import com.zhuanzhuan.hero.user.vo.UserBaseInfoVO;
import com.zhuanzhuan.hero.user.vo.UserBriefInfoVO;
import com.zhuanzhuan.hero.user.vo.UserDetailVO;
import com.zhuanzhuan.hero.user.vo.UserItemBriefVO;
import com.zhuanzhuan.hero.user.vo.label.FraternityAuthLabelVO;
import com.zhuanzhuan.hero.user.vo.label.LabelInfoVO;
import com.zhuanzhuan.hero.user.vo.label.PaltformAuthLabelVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @ClassName UserServiceImpl
 * @Description
 * @Author hanjunjun
 * @Date 2024/6/17 20:45
 */
@Service
@Slf4j
public class UserServiceImpl implements IUserService {
    private static final int USER_BASE_INFO_TIMEOUT = 1000;
    @Resource
    private HeroUserInfoService userInfoService;

    @Resource
    private HeroUserInfoMapper userInfoMapper;

    @Resource
    private HeroUserAuthenticationService userAuthenticationService;

    @Resource
    private HeroUserContactService userContactService;

    @Resource
    private IRiskControlService riskControlService;

    @Resource
    private IApolloService apolloService;

    @Resource
    private IPushService pushService;

    @Resource
    private ImHelper imHelper;

    @Resource
    private HeroUserNotesService userNotesService;

    @Resource
    private HeroSocialHelper heroSocialHelper;

    @Resource
    private HeroMemberHelper heroMemberHelper;

    @Resource
    private HeroUserLabelRelationService labelRelationService;

    @Resource
    private ICounterService counterService;

    @Resource
    private HeroLabelInfoService labelInfoService;

    @Resource
    private IRecentUpdatesService recentUpdatesService;

    @Resource
    private IAttentionService attentionService;

    @Resource
    private HeroUserReliableRecordService reliableRecordService;

    @Resource
    private HeroRecycleOrderHelper heroRecycleOrderHelper;

    @Resource
    private HeroUserProducer heroUserProducer;
    @Resource
    private IFraternityAuthService fraternityAuthService;

    @Resource
    private IUserGroupService userGroupService;

    @Resource
    private HeroSearchHelper heroSearchHelper;

    @Resource
    private UserInfoConvert userInfoConvert;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean doRegister(Long uid, String mobile) {
        log.info("k=s act=doRegister uid={} mobile={}", uid, mobile);
        if (Objects.isNull(uid) || StringUtils.isBlank(mobile)) {
            throw new IllegalArgumentException(ExceptionMsgEnum.PARAM_ERROR.getErrorMsg());
        }

        //是否已注册
        HeroUserInfo existUser = userInfoService.getUserByUid(uid);
        if (Objects.nonNull(existUser)) {
            log.info("用户已存在");
            return true;
        }

        //--------------注册start--------------

        //如果手机号已存在一个非注销的用户  告警出来(尚不清楚中台具体原因)，不阻断
        try {
            this.checkAndWarnExceptionUser(mobile, uid);
        } catch (Exception e) {
            log.error("checkAndWarnExceptionUser异常", e);
        }

        HeroUserInfo heroUserInfo = this.buildRegisterUserInfo(uid, mobile);
        Long userId = userInfoService.insertSelective(heroUserInfo);
        log.info("user_info save finish,id={}", userId);

        //hero_user_contact初始化
        String nickname = heroUserInfo.getNickname();
        String profilePhoto = heroUserInfo.getProfilePhoto();
        Long userContactId = userContactService.registInitUserContactInfo(uid, mobile, nickname, profilePhoto);
        log.info("user_contact save finish,id={}", userContactId);

        //hero_user_authentication初始化
        Long userAuthenticationId = userAuthenticationService.registInitUserAuthenticationInfo(uid);
        log.info("userAuthenticationId={}", userAuthenticationId);

        //同步搜广推
        UserRegisterDTO userRegisterDTO = new UserRegisterDTO();
        userRegisterDTO.setUid(uid);
        userRegisterDTO.setHeadUrl(profilePhoto);
        userRegisterDTO.setNickName(nickname);
        if (!heroSearchHelper.writeUser(userRegisterDTO)) {
            log.error("用户注册同步search失败");
            throw new BusinessException(ExceptionMsgEnum.REGISTER_FAIL);
        }

        //IM注册用户
        imHelper.createImUser(uid, nickname, profilePhoto);

        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean doUnRegist(Long uid) {
        //用户表
        userInfoService.unregistUser(uid);

        //联系方式表   业务逻辑中都是基于该表数据必然存在的大前提，不能删
//        userContactService.delByUid(uid);

        //认证表   不能删
//        userAuthenticationService.delByUid(uid);

        //IM
        imHelper.deleteImUser(uid);

        //搜广推
        if (!heroUserProducer.sendUnregistUpdate(new BaseUserMsg(uid))) {
            log.error("注销发送mq失败");
        }

        return true;
    }

    @Override
    public boolean cancelAccount(Long uid) {


        //im注销
        imHelper.deleteImUser(uid);

        return true;
    }

    @Override
    public void saveUserBaseInfo(Long uid, SaveUserBaseInfoDTO saveUserBaseInfoDTO, ServiceHeaderEntity header) {
        //查询旧数据
        HeroUserInfo dbRecord = userInfoService.getUserByUid(uid);
        Assert.notNull(dbRecord, ExceptionMsgEnum.BUSINESS_ERROR);
        userInfoService.checkCanEdit(dbRecord.getUid());

        //头像、昵称如有修改则调用风控
        boolean needRiskControl = false;
        HeroUserInfo userInfoUpdate = new HeroUserInfo();

        UserBaseInfoRiskControlRequest riskControlRequest = new UserBaseInfoRiskControlRequest();
        if (!Objects.equals(saveUserBaseInfoDTO.getNickname(), dbRecord.getNickname())) {
            riskControlRequest.setNickname(saveUserBaseInfoDTO.getNickname());
            needRiskControl = true;
        }
        if (!Objects.equals(saveUserBaseInfoDTO.getProfilePhoto(), dbRecord.getProfilePhoto())) {
            //保存上次生效的头像
            userInfoUpdate.setLastEffectiveProfilePhoto(dbRecord.getProfilePhoto());
            riskControlRequest.setProfilePicture(saveUserBaseInfoDTO.getProfilePhoto());
            needRiskControl = true;
        }
        if (!Objects.equals(saveUserBaseInfoDTO.getCompanyPosition(), dbRecord.getCompanyPosition())) {
            riskControlRequest.setPosition(saveUserBaseInfoDTO.getCompanyPosition());
            needRiskControl = true;
        }
        if (needRiskControl) {
            RiskControlResult riskControlResult =
                    riskControlService.userBaseInfoRiskControl(uid, header, riskControlRequest);
            if (!(RiskControlResultType.PASS.getCode() == riskControlResult.getResult())) {
                log.info("用户修改基本信息风控不通过");
                throw new BusinessException(ExceptionMsgEnum.BUSINESS_ERROR.getCode(), Consts.RISK_CONTROL_FAIL_TPS);
            }
        }

        //保存
        userInfoUpdate.setNickname(saveUserBaseInfoDTO.getNickname())
                .setProfilePhoto(saveUserBaseInfoDTO.getProfilePhoto())
                .setCompanyPosition(saveUserBaseInfoDTO.getCompanyPosition());
        if (Objects.nonNull(saveUserBaseInfoDTO.getSexCode())) {
            userInfoUpdate.setSex(Integer.valueOf(saveUserBaseInfoDTO.getSexCode()));
        }

        LambdaUpdateWrapper<HeroUserInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(HeroUserInfo::getUid, uid).eq(HeroUserInfo::getState, StateEnum.EFFECTIVE.getCode());
        userInfoService.update(userInfoUpdate, updateWrapper);

        //更新IM用户
        imHelper.updateImUserAsync(uid, saveUserBaseInfoDTO.getNickname(), saveUserBaseInfoDTO.getProfilePhoto());

        //个人信息是否完善 完善则发送mq
        this.personInfoPerfectionBroadcast(uid);

        //通知搜广推
        boolean sendResult = heroUserProducer.sendBaseInfoUpdate(
                new UserBaseInfoMsg(uid, saveUserBaseInfoDTO.getProfilePhoto(), saveUserBaseInfoDTO.getNickname(),
                        saveUserBaseInfoDTO.getCompanyPosition()));
        if (!sendResult) {
            log.error("基本信息更新发送mq失败 uid={}", uid);
        }
    }

    @Override
    public UserBaseInfoVO queryUserBaseInfo(long uid) {
        List<String> fields = new ArrayList<>(Arrays.asList(UserInfoFieldConsts.SEX_CODE, UserInfoFieldConsts.SEX_NAME,
                UserInfoFieldConsts.COMPANY_POSITION));
        return this.selectiveQueryUserBaseInfo(uid, fields);
    }

    @Override
    public boolean userBaseInfoRiskcontrolFail(Long uid, List<String> rejectedFields) {
        log.info("个人信息风控失败,uid={} rejectFields={}", uid, JsonUtils.toJsonWithoutNull(rejectedFields));
        HeroUserInfo dbRecord = userInfoService.getUserByUid(uid);
        if (Objects.isNull(dbRecord)) {
            log.error("风控失败替换违规头像 用户信息不存在 uid={}", uid);
            return true;
        }

        String nickName = null, profilePhoto = null;

        LambdaUpdateWrapper<HeroUserInfo> updateWrapper = new LambdaUpdateWrapper<>();

        if (rejectedFields.contains(RiskControlFieldEnum.NICKNAME.getField())) {
            log.info("昵称风控失败,替换为默认昵称");
            updateWrapper.set(HeroUserInfo::getNickname, nickName = this.initNickname(dbRecord.getMobile()));
        }
        if (rejectedFields.contains(RiskControlFieldEnum.COMPANY_POSITION.getField())) {
            log.info("职位风控失败,清空");
            updateWrapper.set(HeroUserInfo::getCompanyPosition, null);
        }
        if (rejectedFields.contains(RiskControlFieldEnum.PROFILE_PHOTO.getField())) {
            log.info("头像风控失败,替换为上次生效的头像");
            updateWrapper.set(HeroUserInfo::getProfilePhoto, profilePhoto = dbRecord.getLastEffectiveProfilePhoto());
        }

        updateWrapper.set(HeroUserInfo::getUpdateBy, NumConsts.SYSTEM_CODE)
                .eq(HeroUserInfo::getUid, uid).eq(HeroUserInfo::getState, StateEnum.EFFECTIVE.getCode());
        userInfoMapper.update(null, updateWrapper);

        //更新IM用户
        imHelper.updateImUserAsync(uid, nickName, profilePhoto);

        //发送push
        if (CollectionUtils.isNotEmpty(rejectedFields)) {
            rejectedFields.forEach(rejectField -> {
                String rejectTitle = riskControlService.parseTitleByField(rejectField);
                pushService.sendPushAsync(uid, PushHelper.BASE_INFO_TEMPLATE_ID,
                        PushHelper.parseParamMapByField(rejectTitle));
            });
        }

        return true;
    }

    @Override
    public boolean userOuterInfoRiskcontrolFail(Long uid, List<String> rejectedFields) {
        log.info("回收商端外信息风控失败,uid={} rejectFields={}", uid, JsonUtils.toJsonWithoutNull(rejectedFields));
        HeroUserContact dbRecord = userContactService.getByUid(uid);
        if (Objects.isNull(dbRecord)) {
            log.error("风控失败替换违规头像 用户信息不存在 uid={}", uid);
            return true;
        }

        LambdaUpdateWrapper<HeroUserContact> updateWrapper = new LambdaUpdateWrapper<>();
        if (rejectedFields.contains(RiskControlFieldEnum.OUTER_NICKNAME.getField())) {
            log.info("昵称风控失败,替换为端内昵称");
            HeroUserInfo userInfo = userInfoService.getUserByUid(uid);
            Assert.notNull(userInfo, ExceptionMsgEnum.DATA_NOT_EXIST);
            updateWrapper.set(HeroUserContact::getOuterNickname, userInfo.getNickname());
        }
        if (rejectedFields.contains(RiskControlFieldEnum.OUTER_PROFILE_PHOTO.getField())) {
            log.info("头像风控失败,替换为默认头像");
            UserInfoDefaultBO userInfoDefaultBO = apolloService.queryDefauleProperties();
            updateWrapper.set(HeroUserContact::getOuterProfilePhoto, userInfoDefaultBO.getDefaultProfilePhoto());
        }

        updateWrapper.set(HeroUserContact::getUpdateBy, NumConsts.SYSTEM_CODE)
                .eq(HeroUserContact::getUid, uid)
                .eq(HeroUserContact::getState, StateEnum.EFFECTIVE.getCode());
        userContactService.update(updateWrapper);

        //发送push
        if (CollectionUtils.isNotEmpty(rejectedFields)) {
            rejectedFields.forEach(rejectField -> {
                String rejectTitle = riskControlService.parseTitleByField(rejectField);
                pushService.sendPushAsync(uid, PushHelper.OUTER_INFO_TEMPLATE_ID,
                        PushHelper.parseParamMapByField(rejectTitle));
            });
        }

        return true;
    }

    @Override
    public void modifyPersonalIntroduction(Long uid, String personalDescription, ServiceHeaderEntity header) {
        log.info("更新个人简介 uid={}", uid);
        HeroUserInfo heroUserInfo = userInfoService.getUserByUid(uid);
        Assert.notNull(heroUserInfo, ExceptionMsgEnum.BUSINESS_ERROR);

        if (StringUtils.isNotBlank(personalDescription) && !personalDescription.equals(heroUserInfo.getPersonalIntroduction())) {
            //风控
            UserProfileRiskControlRequest riskControlRequest = new UserProfileRiskControlRequest();
            riskControlRequest.setContent(personalDescription);
            RiskControlResult riskControlResult =
                    riskControlService.userPersonIntroductionRiskControl(uid, header, riskControlRequest);
            if (RiskControlResultType.PASS.getCode() != riskControlResult.getResult()) {
                log.info("用户修改个人简介风控不通过");
                throw new BusinessException(ExceptionMsgEnum.BUSINESS_ERROR.getCode(), Consts.RISK_CONTROL_FAIL_TPS);
            }
        }

        //更新表
        HeroUserInfo heroUserInfoUpdate = new HeroUserInfo();
        heroUserInfoUpdate.setPersonalIntroduction(personalDescription);
        userInfoService.updateByUid(uid, heroUserInfoUpdate);
    }

    @Override
    public boolean personIntroductionRiskcontrolFail(Long uid, List<String> rejectedFields) {
        log.info("个人简介风控失败,uid={} rejectFields={}", uid, JsonUtils.toJsonWithoutNull(rejectedFields));
        HeroUserInfo dbRecord = userInfoService.getUserByUid(uid);
        Assert.notNull(dbRecord, ExceptionMsgEnum.BUSINESS_ERROR);

        LambdaUpdateWrapper<HeroUserInfo> updateWrapper = new LambdaUpdateWrapper<>();
        if (rejectedFields.contains(RiskControlFieldEnum.COMPANY_POSITION.getField())) {
            log.info("个人简介风控失败,清空");
            updateWrapper.set(HeroUserInfo::getPersonalIntroduction, null);
        }

        updateWrapper.set(HeroUserInfo::getUpdateBy, NumConsts.SYSTEM_CODE)
                .eq(HeroUserInfo::getUid, uid).eq(HeroUserInfo::getState, StateEnum.EFFECTIVE.getCode());
        userInfoMapper.update(null, updateWrapper);

        //发送push
        if (CollectionUtils.isNotEmpty(rejectedFields)) {
            rejectedFields.forEach(rejectField -> {
                String rejectTitle = riskControlService.parseTitleByField(rejectField);
                pushService.sendPushAsync(uid, PushHelper.MANAGEMENT_LABEL_TEMPLATE_ID,
                        PushHelper.parseParamMapByField(rejectTitle));
            });
        }

        return true;
    }

    @Override
    public List<UserItemBriefVO> buildUserItem(Long selfUid, List<Long> otherUids, boolean needAttentionInfo, boolean needMemberInfo) {
        otherUids = otherUids.stream().distinct().collect(Collectors.toList());
        //查询用户信息
        List<HeroUserInfo> otherUserInfos = userInfoService.listByUid(otherUids);
        //k:otherUid
        Map<Long, HeroUserInfo> otherUserInfoMap =
                otherUserInfos.stream().collect(Collectors.toMap(HeroUserInfo::getUid, Function.identity()));

        //查询备注  selfUid
        List<HeroUserNotes> userNotes = userNotesService.listByUid(selfUid, otherUids);
        //k:otherUid v:备注
        Map<Long, String> otherUserNotesMap =
                userNotes.stream().collect(Collectors.toMap(HeroUserNotes::getToUid, HeroUserNotes::getNotes));

        Map<Long, UserAttentionBO> otherUserAttentionMap = needAttentionInfo ?
            this.queryUserAttentionMap(selfUid, otherUids) : new HashMap<>();

        Map<Long, MemberDTO> uidMemberMap = new HashMap<>();
        List<MemberDTO> memberDTOList = heroMemberHelper.listMember(otherUids);
        if (CollectionUtils.isNotEmpty(memberDTOList)) {
            uidMemberMap.putAll(memberDTOList.stream().collect(Collectors.toMap(MemberDTO::getUid, Function.identity())));
        }

        return otherUids.stream()
                .map(otherUid -> this.convertUserItem(otherUid, otherUserInfoMap, otherUserNotesMap, otherUserAttentionMap,
                        uidMemberMap))
                .collect(Collectors.toList());
    }

    @Override
    public UserBriefInfoVO queryOuterInfo(Long uid) {
        List<String> fields = Arrays.asList(UserInfoFieldConsts.OUTER_NICKNAME, UserInfoFieldConsts.OUTER_PROFILE_PHOTO);

        UserBaseInfoVO userBaseInfoVO = this.selectiveQueryUserBaseInfo(uid, fields);
        if (Objects.isNull(userBaseInfoVO)) {
            return null;
        }

        if (StringUtils.isBlank(userBaseInfoVO.getOuterNickname())) {
            userBaseInfoVO.setOuterNickname(userBaseInfoVO.getNickname());
        }
        if (StringUtils.isBlank(userBaseInfoVO.getOuterProfilePhoto())) {
            userBaseInfoVO.setOuterProfilePhoto(userBaseInfoVO.getProfilePhoto());
        }
        return this.convertUserBriefInfoVO(userBaseInfoVO);
    }

    @Override
    public void updateOuterInfo(Long uid, SaveOuterInfoDTO saveOuterInfoDTO, ServiceHeaderEntity header) {
        //头像昵称过风控
        //查询旧数据
        HeroUserContact dbRecord = userContactService.getByUid(uid);
        Assert.notNull(dbRecord, ExceptionMsgEnum.BUSINESS_ERROR);

        //头像、昵称如有修改则调用风控
        boolean needRiskControl = false;
        RecycleShareRiskControlRequest riskControlRequest = new RecycleShareRiskControlRequest();
        if (!Objects.equals(saveOuterInfoDTO.getNickname(), dbRecord.getOuterNickname())) {
            riskControlRequest.setRecycleName(saveOuterInfoDTO.getNickname());
            needRiskControl = true;
        }
        if (!Objects.equals(saveOuterInfoDTO.getProfilePhoto(), dbRecord.getOuterProfilePhoto())) {
            riskControlRequest.setRecycleProfilePicture(saveOuterInfoDTO.getProfilePhoto());
            needRiskControl = true;
        }

        if (needRiskControl) {
            RiskControlResult riskControlResult =
                    riskControlService.userOuterInfoRiskControl(uid, header, riskControlRequest);
            if (!(RiskControlResultType.PASS.getCode() == riskControlResult.getResult())) {
                log.info("用户修改分享信息风控不通过");
                throw new BusinessException(ExceptionMsgEnum.BUSINESS_ERROR.getCode(), Consts.RISK_CONTROL_FAIL_TPS);
            }
        }

        //更新
        LambdaUpdateWrapper<HeroUserContact> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(HeroUserContact::getOuterNickname, saveOuterInfoDTO.getNickname())
                .set(HeroUserContact::getOuterProfilePhoto, saveOuterInfoDTO.getProfilePhoto())
                .eq(HeroUserContact::getUid, uid)
                .eq(HeroUserContact::getState, StateEnum.EFFECTIVE.getCode());
        userContactService.update(updateWrapper);
    }

    @Override
    public UserDetailVO queryUserDetailInfo(Long loginUid, Long homemakerUid, ServiceHeaderEntity header) {
        UserDetailVO userDetailVO = new UserDetailVO();

        //是否是客态
        boolean isOther = Objects.nonNull(homemakerUid) && !loginUid.equals(homemakerUid);
        Long queryUid = isOther ? homemakerUid : loginUid;

        //用户信息
        HeroUserInfo userInfo = userInfoService.getUserByUid(queryUid);
        Assert.notNull(userInfo, ExceptionMsgEnum.DATA_NOT_EXIST);

        Integer userState = userInfo.getUserState();
        userDetailVO.setUserState(userState);
        if (userInfo.isUnregistered()) {
            log.info("用户已注销");
            return userDetailVO;
        }

        //联系信息
        HeroUserContact userContact = userContactService.getByUid(queryUid);

        userDetailVO.setUid(queryUid);
        this.buildNicknameProfilePhoto(userDetailVO, userInfo, userContact, false, isOther, loginUid);
        userDetailVO.setSexCode(userInfo.getSex()).setSexName(UserSexEnum.getNameByCode(userInfo.getSex()))
                .setCompanyPosition(userInfo.getCompanyPosition());

        //查询apollo配置的认证icon
        DisplayIconBO displayIcon = apolloService.queryDisplayIcon();

        //会员信息
        Integer memberLevel = null;
        MemberDTO member = heroMemberHelper.queryMember(queryUid);
        boolean isMember = heroMemberHelper.isMember(member);
        userDetailVO.setIsMember(isMember ? NumConsts.ONE : NumConsts.ZERO);
        if (isMember) {
            userDetailVO.setMemberLevel(memberLevel = member.getMemberLevel())
                    .setMemberLevelName(member.getMemberLevelName())
                    .setMemberStatus(member.getMemberStatus())
                    .setAvatarFrame(member.getAvatarFrame());
            //邀请官信息
            userDetailVO.setInviter(this.buildInviter(member.getRecommenderId()));
            userDetailVO.setMemberNo(member.getMemberNo());
            if (userInfoService.needHideMemberLevel(header)) {
                //赋值占位图片
                userDetailVO.setMemberLevelPic(displayIcon.getMemberLevelPicPlaceHolder());
            } else {
                //不需要隐藏的时候才赋值
                userDetailVO.setMemberLevelPic(member.getMemberLevelPic());
            }
        } else {
            //填充引导开通会员文案
            userDetailVO.setOpenMemberGuide(apolloService.queryOpenMemberGuide());
        }

        //运营标签
        List<LabelInfoPO> businessLabels =
                labelRelationService.queryUserRealateLabelInfos(Collections.singletonList(queryUid), LabelTypeEnum.BUSINESS.getCode());
        if (CollectionUtils.isNotEmpty(businessLabels)) {
            LabelInfoPO businessLabelInfo = businessLabels.get(NumConsts.ZERO);
            userDetailVO.setBusinessLabelDetail(new LabelInfoVO(businessLabelInfo.getLabelName(), businessLabelInfo.getLabelIcon()));
        }

        //页面url
        PageUrlBO pageUrlBO = apolloService.queryPageUrls();

        //被认证数
        List<UserDetailVO.UserCountInfo> userRecords = this.queryUserCertifedNums(loginUid, queryUid, isOther, pageUrlBO);
        userDetailVO.setUserRecords(userRecords);

        //实人、企业认证
        HeroUserAuthentication userAuthentication = userAuthenticationService.getByUid(queryUid);
        this.buildUserAuthenticationDetail(userDetailVO, userAuthentication);

        //公司职位
        userDetailVO.setCompanyPosition(userInfo.getCompanyPosition());
        //所在地区
        userDetailVO.setRegion(UserInfoConvert.parseRegion(userContact));
        //主营品类
        List<LabelInfoPO> relatedManagementLabelInfos =
                labelRelationService.queryUserRealateLabelInfos(Collections.singletonList(queryUid), LabelTypeEnum.MANAGEMENT.getCode());
        userDetailVO.setMainProductCates(this.buildMainProductCates(relatedManagementLabelInfos, null));

        //平台认证标签
        userDetailVO.setPlatformCertifiedLabels(this.buildPlatformCertifiedLabels(userAuthentication, displayIcon));
        //封面
        userDetailVO.setBackdrop(userInfo.getBackdrop())
                //个人简介
                .setPersonalDescription(userInfo.getPersonalIntroduction())
                //运营审核的身份
                .setCertifiedIdenties(this.buildCertifiedIdenties(queryUid, userAuthentication))
                //服务能力
                .setServiceabilities(this.buildServiceabilities(relatedManagementLabelInfos))
                //信息完善度
                .setPersonInfoPerfectDegree(this.buildPersonInfoPerfectDegree(userInfo, userContact, relatedManagementLabelInfos))
                //靠谱详情页
                .setReliableDetailPagelUrl(String.format(pageUrlBO.getReliableList(), queryUid));

        //优势介绍
        List<LabelInfoPO> relatedAdvantagesLabels =
                labelRelationService.queryUserRealateLabelInfos(Collections.singletonList(queryUid), LabelTypeEnum.ADVANTAGE.getCode());
        userDetailVO.setAdvantagesIntroduction(this.buildAdvantagesIntroduction(relatedAdvantagesLabels, null));

        //功能区
        boolean isShowVisitRecord = NumConsts.ONE.equals(userInfo.getIsShowVisitor());
        userDetailVO.setFunctionalDomain(
                        this.buildFunctionalDomain(userInfo, displayIcon, memberLevel, pageUrlBO, isOther, isShowVisitRecord))
                .setShowVisitRecord(isOther ? isShowVisitRecord : null);

        if (isOther) {
            //联系方式是否可见
            ContactVisibleBO contactVisibleBO = this.contactVisible(loginUid, userContact.getUid(), userContact);
            if (contactVisibleBO.getIsVisible()) {
                userDetailVO.setStoreAddress(userContact.joinAbsoluteStoreAddress());
            }
            //联系方式
            userDetailVO.setContactInformations(this.buildContactInformations(contactVisibleBO, userContact, displayIcon,
                            memberLevel))
                    //靠谱按钮
                    .setReliableBtn(this.buildReliableBtn(loginUid, queryUid));
        }

        //近期动态
        try {
            userDetailVO.setRecentUpdates(recentUpdatesService.queryUserRecentUpdates(queryUid));
        } catch (Exception e) {
            //报错不影响其他数据
            log.error("用户近期动态计算错误", e);
        }

        return userDetailVO;
    }

    @Override
    public UserDetailVO queryUserDetailInfoOuter(Long uid) {
        UserDetailVO userDetailVO = new UserDetailVO();

        //用户信息
        HeroUserInfo userInfo = userInfoService.getUserByUid(uid);
        Assert.notNull(userInfo, ExceptionMsgEnum.DATA_NOT_EXIST);

        Integer userState = userInfo.getUserState();
        userDetailVO.setUserState(userState);
        if (userInfo.isUnregistered()) {
            log.info("用户已注销");
            return userDetailVO;
        }

        //联系信息
        HeroUserContact userContact = userContactService.getByUid(uid);

        userDetailVO.setUid(uid);
        this.buildNicknameProfilePhoto(userDetailVO, userInfo, userContact, true, false, null);
        //职位
        userDetailVO.setCompanyPosition(userInfo.getCompanyPosition());
        //所在地区
        userDetailVO.setRegion(UserInfoConvert.parseRegion(userContact));

        //实人、企业认证
        HeroUserAuthentication userAuthentication = userAuthenticationService.getByUid(uid);
        this.buildUserAuthenticationDetail(userDetailVO, userAuthentication);

        //主营品类
        List<LabelInfoPO> managementLabelInfos =
                labelRelationService.queryUserRealateLabelInfos(Collections.singletonList(uid), LabelTypeEnum.MANAGEMENT.getCode());
        userDetailVO.setMainProductCates(this.buildMainProductCates(managementLabelInfos, null));

        //优势介绍
        List<LabelInfoPO> relatedAdvantagesLabels =
                labelRelationService.queryUserRealateLabelInfos(Collections.singletonList(uid), LabelTypeEnum.ADVANTAGE.getCode());
        userDetailVO.setAdvantagesIntroduction(this.buildAdvantagesIntroduction(relatedAdvantagesLabels, null));

        //平台认证标签
        DisplayIconBO displayIcon = apolloService.queryDisplayIcon();
        userDetailVO.setPlatformCertifiedLabels(this.buildPlatformCertifiedLabels(userAuthentication, displayIcon));

        //会员信息
        Integer memberLevel = null;
        MemberDTO member = heroMemberHelper.queryMember(uid);
        boolean isMember = heroMemberHelper.isMember(member);
        userDetailVO.setIsMember(isMember ? NumConsts.ONE : NumConsts.ZERO);
        if (isMember) {
            userDetailVO.setMemberLevel(memberLevel = member.getMemberLevel())
                    .setMemberLevelName(member.getMemberLevelName())
                    .setAvatarFrame(member.getAvatarFrame());
        }

        //联系方式可见
        ContactVisibleBO contactVisibleBO = ContactVisibleBO.visible();
        //联系方式
        userDetailVO.setContactInformations(this.buildContactInformations(contactVisibleBO, userContact, displayIcon,
                memberLevel));

        return userDetailVO;
    }

    @Override
    public List<UserBaseInfoVO> batchQueryUserBaseInfo(BatchQueryUserInfoSelectiveDTO queryDTO) {
        Long fromUid = queryDTO.getFromUid();
        List<Long> toUids = queryDTO.getUids();
        //用户信息
        List<String> queryFields = queryDTO.getFields() == null ? new ArrayList<>() : queryDTO.getFields();
        CompletableFuture<List<HeroUserInfo>> userInfosFuture = AsyncUtil.call(() -> userInfoService.listByUid(toUids), ThreadPoolConfiguration.USER_BASE_INFO_EXECUTOR);
        //联系信息
        CompletableFuture<Map<Long, HeroUserContact>> userContactMapFuture =
                AsyncUtil.call(() -> {
                    List<HeroUserContact> userContacts = userContactService.listByUid(toUids);
                    Map<Long, HeroUserContact> userContactMap =
                            userContacts.stream().collect(Collectors.toMap(HeroUserContact::getUid, Function.identity()));
                    return userContactMap;
                }, ThreadPoolConfiguration.USER_BASE_INFO_EXECUTOR);

        //会员信息
        CompletableFuture<Map<Long, MemberDTO>> memberMapFuture =
                AsyncUtil.call(() -> {
                    Map<Long, MemberDTO> map = new HashMap<>();
                    if (queryFields.contains(UserInfoFieldConsts.MEMBER_LEVEL)) {
                        List<MemberDTO> members = heroMemberHelper.listMember(toUids);
                        map.putAll(members.stream().collect(Collectors.toMap(MemberDTO::getUid, Function.identity())));
                    }
                    return map;
                }, ThreadPoolConfiguration.USER_BASE_INFO_EXECUTOR);

        //运营标签
        CompletableFuture<Map<Long, LabelInfoPO>> businessLabelMapFuture =
                AsyncUtil.call(() -> {
                    Map<Long, LabelInfoPO> businessLabelMap = new HashMap<>();
                    if (queryFields.contains(UserInfoFieldConsts.BUSINESS_LABEL)) {
                        List<LabelInfoPO> businessLabels =
                                labelRelationService.queryUserRealateLabelInfos(toUids, LabelTypeEnum.BUSINESS.getCode());
                        businessLabelMap.putAll(businessLabels.stream().collect(Collectors.toMap(LabelInfoPO::getUid, Function.identity())));
                    }
                    return businessLabelMap;
                }, ThreadPoolConfiguration.USER_BASE_INFO_EXECUTOR);
        //备注
        CompletableFuture<Map<Long, String>> userCommentMapFuture =
                AsyncUtil.call(() -> {
                    Map<Long, String> userCommentMap = new HashMap<>();
                    if (queryFields.contains(UserInfoFieldConsts.USER_COMMENTS)) {
                        List<HeroUserNotes> userNotes = userNotesService.listByUid(fromUid, toUids);
                        //k:otherUid v:备注
                        userCommentMap.putAll(userNotes.stream().collect(Collectors.toMap(HeroUserNotes::getToUid, HeroUserNotes::getNotes)));
                    }
                    return userCommentMap;
                }, ThreadPoolConfiguration.USER_BASE_INFO_EXECUTOR);
        //关注等级
        CompletableFuture<Map<Long, UserAttentionBO>> userAttentionMapFuture =
                AsyncUtil.call(() -> {
                    Map<Long, UserAttentionBO> userAttentionMap = new HashMap<>();
                    if (queryFields.contains(UserInfoFieldConsts.ATTENTION_RELEATION_CODE)) {
                        userAttentionMap.putAll(this.queryUserAttentionMap(fromUid, toUids));
                    }
                    return userAttentionMap;
                }, ThreadPoolConfiguration.USER_BASE_INFO_EXECUTOR);
        //平台认证标签
        CompletableFuture<Map<Long, HeroUserAuthentication>> userAuthenticationMapFuture =
                AsyncUtil.call(() -> {
                    Map<Long, HeroUserAuthentication> userAuthenticationMap = new HashMap<>();
                    if (queryFields.contains(UserInfoFieldConsts.PLATFORM_CERTIFIED_LABELS)) {
                        List<HeroUserAuthentication> userAuthentications = userAuthenticationService.listByUid(toUids);
                        //k:otherUid v:备注
                        userAuthenticationMap.putAll(userAuthentications.stream()
                                .collect(Collectors.toMap(HeroUserAuthentication::getUid, Function.identity())));
                    }
                    return userAuthenticationMap;
                }, ThreadPoolConfiguration.USER_BASE_INFO_EXECUTOR);

        String defaultProfilePhoto = apolloService.queryDefauleProperties().getDefaultProfilePhoto();
        DisplayIconBO displayIcon = apolloService.queryDisplayIcon();
        List<HeroUserInfo> userInfos = AsyncUtil.result(userInfosFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Lists.newArrayList(), fromUid, toUids);
        if(CollectionUtils.isEmpty(userInfos)){
            return Lists.newArrayList();
        }
        Map<Long, HeroUserContact> userContactMap = AsyncUtil.result(userContactMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        Map<Long, LabelInfoPO> businessLabelMap = AsyncUtil.result(businessLabelMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        Map<Long, MemberDTO> memberMap = AsyncUtil.result(memberMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        Map<Long, String> userCommentMap = AsyncUtil.result(userCommentMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        Map<Long, HeroUserAuthentication> userAuthenticationMap = AsyncUtil.result(userAuthenticationMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        Map<Long, UserAttentionBO> userAttentionMap = AsyncUtil.result(userAttentionMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        return userInfos.stream().map(userInfo -> {
            Long uid = userInfo.getUid();
            return this.convertUserBaseInfo(userInfo, userContactMap.get(uid), memberMap.get(uid), businessLabelMap.get(uid),
                    queryFields, userCommentMap.get(uid), false, defaultProfilePhoto, userAuthenticationMap.get(uid),
                displayIcon, userAttentionMap.get(uid));
        }).collect(Collectors.toList());
    }

    @Override
    public UserBaseInfoVO queryUserBaseInfoSelective(QueryUserInfoDTO queryUserInfoDTO) {
        Long fromUid = queryUserInfoDTO.getUid();
        Long toUid = queryUserInfoDTO.getToUid();
        String registMobile = queryUserInfoDTO.getRegistMobile();
        if (Objects.isNull(toUid) && StringUtils.isBlank(registMobile)) {
            throw new IllegalArgumentException(ExceptionMsgEnum.PARAM_ERROR.getErrorMsg());
        }

        QueryUserInfoParam param = new QueryUserInfoParam();
        if (Objects.nonNull(toUid)) {
            param.setUids(Collections.singletonList(toUid));
        }
        param.setRegistMobile(registMobile);
        List<UserPO> userInfos = userInfoService.listByParam(param);
        if (CollectionUtils.isEmpty(userInfos)) {
            return null;
        }
        BatchQueryUserInfoSelectiveDTO batchQueryDTO = new BatchQueryUserInfoSelectiveDTO();
        batchQueryDTO.setFromUid(fromUid);
        batchQueryDTO.setUids(userInfos.stream().map(UserPO::getUid).collect(Collectors.toList()));
        batchQueryDTO.setFields(queryUserInfoDTO.getFields());
        List<UserBaseInfoVO> userBaseInfos = this.batchQueryUserBaseInfo(batchQueryDTO);
        if (CollectionUtils.isEmpty(userBaseInfos)) {
            return null;
        }

        return userBaseInfos.get(NumConsts.ZERO);
    }

    @Override
    public List<UserDetailDTO> batchGetUserDetail(Long fromUid, List<Long> toUids, ServiceHeaderEntity header) {
        //用户信息
        List<HeroUserInfo> userInfos = userInfoService.listByUid(toUids);
        if (CollectionUtils.isEmpty(userInfos)) {
            return new ArrayList<>();
        }
        //认证信息
        CompletableFuture<Map<Long, HeroUserAuthentication>> userAuthenticationMapFuture = AsyncUtil.call(()->{
            List<HeroUserAuthentication> userAuthentications = userAuthenticationService.listByUid(toUids);
            Map<Long, HeroUserAuthentication> userAuthenticationMap =
                    userAuthentications.stream().collect(Collectors.toMap(HeroUserAuthentication::getUid, Function.identity()));
            return userAuthenticationMap;
        }, ThreadPoolConfiguration.USER_DETAIL_EXECUTOR);

        //联系信息
        CompletableFuture<Map<Long, HeroUserContact>> userContactsFuture = AsyncUtil.call(()->{
            List<HeroUserContact> userContacts = userContactService.listByUid(toUids);
            Map<Long, HeroUserContact> userContactMap =
                    userContacts.stream().collect(Collectors.toMap(HeroUserContact::getUid, Function.identity()));
            return userContactMap;
        }, ThreadPoolConfiguration.USER_DETAIL_EXECUTOR);

        //会员信息
        CompletableFuture<Map<Long, MemberDTO>> memberMapFuture = AsyncUtil.call(()->{
            List<MemberDTO> members = heroMemberHelper.listMember(toUids);
            Map<Long, MemberDTO> memberMap = members.stream().collect(Collectors.toMap(MemberDTO::getUid, Function.identity()));
            return memberMap;
        }, ThreadPoolConfiguration.USER_DETAIL_EXECUTOR);


        //运营标签
        CompletableFuture<Map<Long, LabelInfoPO>> businessLabelMapFuture = AsyncUtil.call(()->{
            List<LabelInfoPO> businessLabels =
                    labelRelationService.queryUserRealateLabelInfos(toUids, LabelTypeEnum.BUSINESS.getCode());
            Map<Long, LabelInfoPO> businessLabelMap =
                    businessLabels.stream().collect(Collectors.toMap(LabelInfoPO::getUid, Function.identity()));
            return businessLabelMap;
        }, ThreadPoolConfiguration.USER_DETAIL_EXECUTOR);

        //备注
        CompletableFuture<Map<Long, String>> userCommentMapFuture = AsyncUtil.call(()->{
            Map<Long, String> userCommentMap = new HashMap<>();
            if (Objects.nonNull(fromUid)) {
                List<HeroUserNotes> userNotes = userNotesService.listByUid(fromUid, toUids);
                //k:otherUid v:备注
                userCommentMap.putAll(userNotes.stream().collect(Collectors.toMap(HeroUserNotes::getToUid, HeroUserNotes::getNotes)));
            }
            return userCommentMap;
        }, ThreadPoolConfiguration.USER_DETAIL_EXECUTOR);
        String defaultProfilePhoto = apolloService.queryDefauleProperties().getDefaultProfilePhoto();
        DisplayIconBO displayIcon = apolloService.queryDisplayIcon();
        boolean needHideMemberLevel = userInfoService.needHideMemberLevel(header);
        Map<Long, HeroUserContact> userContactMap = AsyncUtil.result(userContactsFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        Map<Long, MemberDTO> memberMap = AsyncUtil.result(memberMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        Map<Long, LabelInfoPO> businessLabelMap = AsyncUtil.result(businessLabelMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        Map<Long, String> userCommentMap = AsyncUtil.result(userCommentMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        Map<Long, HeroUserAuthentication> userAuthenticationMap = AsyncUtil.result(userAuthenticationMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);


        return userInfos.stream().map(userInfo -> {
            Long uid = userInfo.getUid();
            return this.convertUserDetailInfo(userInfo, userContactMap.get(uid), memberMap.get(uid),
                    businessLabelMap.get(uid), userCommentMap.get(uid), defaultProfilePhoto, userAuthenticationMap.get(uid),
                    displayIcon, needHideMemberLevel);
        }).collect(Collectors.toList());
    }

    @Override
    public List<UserDetailVO> batchGetUserDetail4Homepage(Long fromUid, List<Long> sourceToUids, ServiceHeaderEntity header) {
        log.info("batchGetUserDetail4Homepage");

        if (CollectionUtils.isEmpty(sourceToUids)) {
            return new ArrayList<>();
        }
        List<Long> toUids = sourceToUids.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList());

        //用户信息
        List<HeroUserInfo> userInfos = userInfoService.listByUid(toUids);
        if (CollectionUtils.isEmpty(userInfos)) {
            return new ArrayList<>();
        }

        //异步计算近期动态
        CompletableFuture<Map<Long, List<String>>> userRecentFuture =
                AsyncUtil.call(() -> recentUpdatesService.batchQueryUserRecentUpdates(toUids), ThreadPoolConfiguration.HOME_PAGE_INFO_EXECUTOR);

        //联系信息
        CompletableFuture<Map<Long, HeroUserContact>> userContactMapFuture = AsyncUtil.call(() -> {
            List<HeroUserContact> userContacts = userContactService.listByUid(toUids);
            Map<Long, HeroUserContact> userContactMap =
                    userContacts.stream().collect(Collectors.toMap(HeroUserContact::getUid, Function.identity()));
            return userContactMap;
        },ThreadPoolConfiguration.HOME_PAGE_INFO_EXECUTOR);


        //认证信息
        CompletableFuture<Map<Long, HeroUserAuthentication>> userAuthenticationMapFuture = AsyncUtil.call(() -> {
            List<HeroUserAuthentication> userAuthentications = userAuthenticationService.listByUid(toUids);
            Map<Long, HeroUserAuthentication> userAuthenticationMap =
                    userAuthentications.stream().collect(Collectors.toMap(HeroUserAuthentication::getUid, Function.identity()));

            return userAuthenticationMap;
        },ThreadPoolConfiguration.HOME_PAGE_INFO_EXECUTOR);

        //会员信息
        CompletableFuture<Map<Long, MemberDTO>> memberMapFuture = AsyncUtil.call(() -> {
            List<MemberDTO> members = heroMemberHelper.listMember(toUids);
            Map<Long, MemberDTO> memberMap = members.stream().collect(Collectors.toMap(MemberDTO::getUid, Function.identity()));
            return memberMap;
        },ThreadPoolConfiguration.HOME_PAGE_INFO_EXECUTOR);


        //运营标签
        CompletableFuture<Map<Long, LabelInfoPO>> businessLabelMapFuture = AsyncUtil.call(() -> {
            List<LabelInfoPO> businessLabels =
                    labelRelationService.queryUserRealateLabelInfos(toUids, LabelTypeEnum.BUSINESS.getCode());
            Map<Long, LabelInfoPO> businessLabelMap =
                    businessLabels.stream().collect(Collectors.toMap(LabelInfoPO::getUid, Function.identity()));
            return businessLabelMap;
        },ThreadPoolConfiguration.HOME_PAGE_INFO_EXECUTOR);

        CompletableFuture<Map<Long, List<String>>> groupLabelsFuture = AsyncUtil.call(() -> {
            Map<Long, List<String>> groupLabels = userGroupService.getGroupLabels(fromUid, toUids);
            return groupLabels;
        },ThreadPoolConfiguration.HOME_PAGE_INFO_EXECUTOR);


        boolean needHideMemberLevel = userInfoService.needHideMemberLevel(header);

        //查询关系等级
        CompletableFuture<Map<Long, UserAttentionBO>> userAttentionMapFuture = AsyncUtil.call(() -> {
            List<UserAttentionBO> otherUserAttentions = heroSocialHelper.queryserAttentions(fromUid, toUids);
            //k:访问者的uid
            Map<Long, UserAttentionBO> userAttentionMap = otherUserAttentions.stream().collect(Collectors.toMap(UserAttentionBO::getToUid, Function.identity()));
            return userAttentionMap;
        },ThreadPoolConfiguration.HOME_PAGE_INFO_EXECUTOR);


        //经营标签
        CompletableFuture<Map<Long, List<LabelInfoPO>>> uidManagementLabelMapFuture = AsyncUtil.call(() -> {
            List<LabelInfoPO> managementLabelInfos = labelRelationService.queryUserRealateLabelInfos(toUids, LabelTypeEnum.MANAGEMENT.getCode());
            Map<Long, List<LabelInfoPO>> uidManagementLabelMap =
                    managementLabelInfos.stream().collect(Collectors.groupingBy(LabelInfoPO::getUid));
            return uidManagementLabelMap;
        },ThreadPoolConfiguration.HOME_PAGE_INFO_EXECUTOR);

        CompletableFuture<List<HeroLabelInfo>> allManagementLabelInfosFuture = AsyncUtil.call(() -> {
            LabelInfoQueryBO queryBO = LabelInfoQueryBO.builder().labelType(LabelTypeEnum.MANAGEMENT.getCode()).build();
            List<HeroLabelInfo> allManagementLabelInfos = labelInfoService.listByParam(queryBO);
            return allManagementLabelInfos;
        },ThreadPoolConfiguration.HOME_PAGE_INFO_EXECUTOR);
        //优势介绍
        CompletableFuture<Map<Long, List<LabelInfoPO>>> uidAdvantagesLabelMapFuture = AsyncUtil.call(() -> {
            List<LabelInfoPO> relatedAdvantagesLabels =
                    labelRelationService.queryUserRealateLabelInfos(toUids, LabelTypeEnum.ADVANTAGE.getCode());
            Map<Long, List<LabelInfoPO>> uidAdvantagesLabelMap =
                    relatedAdvantagesLabels.stream().collect(Collectors.groupingBy(LabelInfoPO::getUid));
            return uidAdvantagesLabelMap;
        },ThreadPoolConfiguration.HOME_PAGE_INFO_EXECUTOR);

        CompletableFuture<List<HeroLabelInfo>> allAdvantagesLabelInfosFuture = AsyncUtil.call(() -> {
            List<HeroLabelInfo> allAdvantagesLabelInfos = labelInfoService.listByParam(
                    LabelInfoQueryBO.builder().labelType(LabelTypeEnum.ADVANTAGE.getCode()).build());
            return allAdvantagesLabelInfos;
        },ThreadPoolConfiguration.HOME_PAGE_INFO_EXECUTOR);

        //同行认证标签
        CompletableFuture<Map<Long, List<FraternityAuthLabelVO>>> fraternityAuthLabelMapFuture = AsyncUtil.call(() -> {
            Map<Long, List<FraternityAuthLabelVO>> fraternityAuthLabelMap = fraternityAuthService.queryBoundedFraternityAuthLabels(toUids);
            return fraternityAuthLabelMap;
        },ThreadPoolConfiguration.HOME_PAGE_INFO_EXECUTOR);

        //备注
        CompletableFuture<Map<Long, String>> userCommentMapFuture = AsyncUtil.call(() -> {
            Map<Long, String> userCommentMap = new HashMap<>();
            if (Objects.nonNull(fromUid)) {
                List<HeroUserNotes> userNotes = userNotesService.listByUid(fromUid, toUids);
                //k:otherUid v:备注
                userCommentMap.putAll(userNotes.stream().collect(Collectors.toMap(HeroUserNotes::getToUid, HeroUserNotes::getNotes)));
            }
            return userCommentMap;

        },ThreadPoolConfiguration.HOME_PAGE_INFO_EXECUTOR);

        //-------------用户统计数------------
        //同行关注数
        CompletableFuture<Map<Long, Long>> followedNumMapFuture = AsyncUtil.call(() -> {
            Map<Long, Long> followedNumMap = counterService.batchQueryFollowedNum(toUids);
            return followedNumMap;
        },ThreadPoolConfiguration.HOME_PAGE_INFO_EXECUTOR);
        //xxx也关注ta
        CompletableFuture<Map<Long, List<String>>> fansProfilePhotoMapFuture = AsyncUtil.call(() -> {
            Map<Long, List<String>> fansProfilePhotoMap = heroSocialHelper.batchQueryContactList(fromUid, toUids);
            return fansProfilePhotoMap;
        },ThreadPoolConfiguration.HOME_PAGE_INFO_EXECUTOR);

        //靠谱值
        CompletableFuture<Map<Long, Long>> reliableNumMapFuture = AsyncUtil.call(() -> {
            Map<Long, Long> reliableNumMap = counterService.batchQueryCertifiedReliableNum(toUids);
            return reliableNumMap;
        },ThreadPoolConfiguration.HOME_PAGE_INFO_EXECUTOR);

        //交易订单数
        CompletableFuture<Map<Long, Long>> dealSuccessOrderMapFuture = AsyncUtil.call(() -> {
            Map<Long, Long> dealSuccessOrderMap = counterService.batchQueryDealSuccessRecycleOrderNum(toUids);
            return dealSuccessOrderMap;
        },ThreadPoolConfiguration.HOME_PAGE_INFO_EXECUTOR);

        //查询apollo配置的认证icon
        DisplayIconBO displayIcon = apolloService.queryDisplayIcon();

        //近期动态
        Map<Long, List<String>> userRecentMap = new HashMap<>();
        try {
            userRecentMap.putAll(AsyncUtil.result(userRecentFuture, RecentUpdatesServiceImpl.RECENT_MSG_ASSEMBLE_TIMEOUT,
                    TimeUnit.MILLISECONDS));
        } catch (Exception e) {
            log.error("计算近期动态失败", e);
        }
        Map<Long, HeroUserContact> userContactMap = AsyncUtil.result(userContactMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        Map<Long, MemberDTO> memberMap = AsyncUtil.result(memberMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        Map<Long, HeroUserAuthentication> userAuthenticationMap = AsyncUtil.result(userAuthenticationMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        Map<Long, List<LabelInfoPO>> uidManagementLabelMap = AsyncUtil.result(uidManagementLabelMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        List<HeroLabelInfo> allManagementLabelInfos = AsyncUtil.result(allManagementLabelInfosFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Lists.newArrayList(), fromUid, toUids);
        Map<Long, List<LabelInfoPO>> uidAdvantagesLabelMap = AsyncUtil.result(uidAdvantagesLabelMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        Map<Long, UserAttentionBO> userAttentionMap = AsyncUtil.result(userAttentionMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        Map<Long, List<FraternityAuthLabelVO>> fraternityAuthLabelMap = AsyncUtil.result(fraternityAuthLabelMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        List<HeroLabelInfo> allAdvantagesLabelInfos = AsyncUtil.result(allAdvantagesLabelInfosFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Lists.newArrayList(), fromUid, toUids);
        Map<Long, String> userCommentMap = AsyncUtil.result(userCommentMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        Map<Long, Long> followedNumMap = AsyncUtil.result(followedNumMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        Map<Long, List<String>> fansProfilePhotoMap = AsyncUtil.result(fansProfilePhotoMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        Map<Long, Long> reliableNumMap = AsyncUtil.result(reliableNumMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        Map<Long, Long> dealSuccessOrderMap = AsyncUtil.result(dealSuccessOrderMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        Map<Long, LabelInfoPO> businessLabelMap = AsyncUtil.result(businessLabelMapFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        Map<Long, List<String>> groupLabels = AsyncUtil.result(groupLabelsFuture, USER_BASE_INFO_TIMEOUT, TimeUnit.MILLISECONDS, Maps.newHashMap(), fromUid, toUids);
        log.info("convertUserDetailInfoForHomepage");
        return userInfos.stream().map(userInfo -> {
            Long uid = userInfo.getUid();
            ConvertUserDetailInfoForHomepageBO convertBO = new ConvertUserDetailInfoForHomepageBO();
            convertBO.setFromUid(fromUid).setUserInfo(userInfo).setUserContact(userContactMap.get(uid))
                    .setMember(memberMap.get(uid)).setBusinessLabel(businessLabelMap.get(uid))
                    .setNeedHideMemberLevel(needHideMemberLevel)
                    .setUserAuthentication(userAuthenticationMap.get(uid))
                    .setManagementLabels(uidManagementLabelMap.get(uid))
                    .setAllManagementLabelInfos(allManagementLabelInfos)
                    .setAdvantagesLabels(uidAdvantagesLabelMap.get(uid)).setAllAdvantagesLabelInfos(allAdvantagesLabelInfos)
                    .setUserAttentionBO(userAttentionMap.get(uid)).setUserRecents(userRecentMap.get(uid))
                    .setFraternityAuthLabels(fraternityAuthLabelMap.get(uid)).setGroupLabels(groupLabels.get(uid))
                    .setDisplayIcon(displayIcon).setUserCommentMap(userCommentMap)
                    .setFollwedNum(followedNumMap.get(uid))
                    .setFansProfilePhotos(fansProfilePhotoMap.get(uid))
                    .setCertifiedReliableNum(reliableNumMap.get(uid))
                    .setDealSuccessOrderNum(dealSuccessOrderMap.get(uid));
            return this.convertUserDetailInfoForHomepage(convertBO);
        }).filter(Objects::nonNull).collect(Collectors.toList());
    }

    @Override
    public void saveUserBackdrop(Long uid, String backdrop, ServiceHeaderEntity header) {
        //查询旧数据
        HeroUserInfo dbRecord = userInfoService.getUserByUid(uid);
        Assert.notNull(dbRecord, ExceptionMsgEnum.BUSINESS_ERROR);
        userInfoService.checkCanEdit(dbRecord.getUid());

        //头像、昵称如有修改则调用风控
        boolean needRiskControl = false;
        HeroUserInfo userInfoUpdate = new HeroUserInfo();

        String lastBckdrop = dbRecord.getBackdrop();
        UserCoverRiskControlRequest riskControlRequest = new UserCoverRiskControlRequest();
        if (!Objects.equals(backdrop, lastBckdrop)) {
            riskControlRequest.setCover(backdrop);
            needRiskControl = true;
        }
        if (needRiskControl) {
            RiskControlResult riskControlResult =
                    riskControlService.userBackdropRiskControl(uid, header, riskControlRequest);
            if (!(RiskControlResultType.PASS.getCode() == riskControlResult.getResult())) {
                log.info("用户背景图风控不通过");
                throw new BusinessException(ExceptionMsgEnum.BUSINESS_ERROR.getCode(), Consts.RISK_CONTROL_FAIL_TPS);
            }
        }

        //更新  旧的暂存
        userInfoUpdate.setBackdrop(backdrop).setLastEffectiveBackdrop(lastBckdrop);

        LambdaUpdateWrapper<HeroUserInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(HeroUserInfo::getUid, uid).eq(HeroUserInfo::getState, StateEnum.EFFECTIVE.getCode());
        userInfoService.update(userInfoUpdate, updateWrapper);
    }

    @Override
    public boolean backdropControlFail(Long uid, List<String> rejectedFields) {
        log.info("背景图风控失败,uid={} rejectFields={}", uid, JsonUtils.toJsonWithoutNull(rejectedFields));
        HeroUserInfo dbRecord = userInfoService.getUserByUid(uid);
        Assert.notNull(dbRecord, ExceptionMsgEnum.BUSINESS_ERROR);

        LambdaUpdateWrapper<HeroUserInfo> updateWrapper = new LambdaUpdateWrapper<>();
        if (rejectedFields.contains(RiskControlFieldEnum.USER_BACKDROP.getField())) {
            log.info("背景图风控失败,替换");
            updateWrapper.set(HeroUserInfo::getBackdrop, dbRecord.getLastEffectiveBackdrop());
        }

        updateWrapper.set(HeroUserInfo::getUpdateBy, NumConsts.SYSTEM_CODE)
                .eq(HeroUserInfo::getUid, uid).eq(HeroUserInfo::getState, StateEnum.EFFECTIVE.getCode());
        userInfoMapper.update(null, updateWrapper);

        //发送push
        if (CollectionUtils.isNotEmpty(rejectedFields)) {
            String rejectTitle = riskControlService.parseTitleByField(rejectedFields.get(NumConsts.ZERO));
            pushService.sendPushAsync(uid, PushHelper.BACKDROP_TEMPLATE_ID,
                PushHelper.parseParamMapByField(rejectTitle));
        }

        return true;
    }

    @Override
    public boolean personInfoPerfection(Long uid, HeroUserInfo userInfo, HeroUserContact userContact,
                                        List<LabelInfoPO> managementLabelInfos) {
        //基本信息
        if (!userInfoService.baseInfoIsPerfection(uid, userInfo)) {
            return false;
        }

        //联系方式
        if (!userContactService.contactInfoIsPerfection(uid, userContact)) {
            return false;
        }

        //经营标签
        if (!labelRelationService.managementLabelIsPerfection(uid, managementLabelInfos)) {
            return false;
        }

        return true;
    }

    @Override
    public void personInfoPerfectionBroadcast(Long uid) {
        //异步加重试
        AsyncUtil.run(() -> {
            boolean isPerfect = this.personInfoPerfection(uid, null, null, null);
            if (isPerfect) {
                log.info("{}信息完善，发送mq通知搜广推", uid);
                if (!heroUserProducer.sendPersonInfoPerfection(new BaseUserMsg(uid))) {
                    log.error("sendPersonInfoPerfection失败");
                    throw new BusinessException(ExceptionMsgEnum.BUSINESS_ERROR);
                }
            }
        });
    }

    private UserDetailDTO convertUserDetailInfo(HeroUserInfo userInfo, HeroUserContact userContact, MemberDTO memberDTO,
        LabelInfoPO labelInfoPO, String userComments, String defaultProfilePhoto,
        HeroUserAuthentication userAuthentication, DisplayIconBO displayIcon, boolean needHideMemberLevel) {
        UserBaseInfoVO userBaseInfo =
                this.convertUserBaseInfo(userInfo, userContact, memberDTO, labelInfoPO, null, userComments,
                        true, defaultProfilePhoto, null, null, null);
        UserDetailDTO userDetail = new UserDetailDTO();
        BeanUtils.copyProperties(userBaseInfo, userDetail);
        //个人简介
        userDetail.setPersonalDescription(userInfo.getPersonalIntroduction());

        if (Objects.nonNull(labelInfoPO)) {
            userDetail.setBusinessLabelDetail(new LabelInfoVO(labelInfoPO.getLabelName(), labelInfoPO.getLabelIcon()));
        }
        if (Objects.nonNull(memberDTO)) {
            if (needHideMemberLevel) {
                //赋值占位图片
                userDetail.setMemberLevelPic(displayIcon.getMemberLevelPicPlaceHolder());
            } else {
                //不需要隐藏的时候才赋值
                userDetail.setMemberLevelPic(memberDTO.getMemberLevelPic());
            }
        }

        //实人认证
        userDetail.setRealPersonCertified(NumConsts.ONE.equals(userAuthentication.getIsRealNameAuth()));
        //企业认证
        userDetail.setEnterpriseCertified(NumConsts.ONE.equals(userAuthentication.getIsEnterpriseAuth()))
                .setEnterpriseName(userAuthentication.getEnterpriseName());
        //地区
        userDetail.setRegion(UserInfoConvert.parseRegion(userContact));
        //平台认证
        userDetail.setPlatformCertifiedLabels(this.buildPlatformCertifiedLabels(userAuthentication, displayIcon));
        //是否已注销
        userDetail.setIsCancelAccount(userInfo.isUnregistered());

        return userDetail;
    }


    private UserDetailVO convertUserDetailInfoForHomepage(ConvertUserDetailInfoForHomepageBO convertBO) {
        HeroUserInfo userInfo = convertBO.getUserInfo();

        //首页列表不展示已注销的
        if (userInfo.isUnregistered()) {
            return null;
        }

        Long fromUid = convertBO.getFromUid();
        Long uid = userInfo.getUid();
        HeroUserContact userContact = convertBO.getUserContact();
        DisplayIconBO displayIcon = convertBO.getDisplayIcon();

        UserDetailVO userDetail = new UserDetailVO();
        userDetail.setUid(uid);
        this.buildNicknameProfilePhoto(userDetail, userInfo, userContact, false, false, fromUid);

        //备注
        userDetail.setUserComments(convertBO.getUserCommentMap().get(uid));

        //会员信息
        MemberDTO member = convertBO.getMember();
        boolean isMember = heroMemberHelper.isMember(member);
        userDetail.setIsMember(isMember ? NumConsts.ONE : NumConsts.ZERO);
        if (isMember) {
            userDetail.setMemberLevel(member.getMemberLevel())
                    .setMemberLevelName(member.getMemberLevelName())
                    .setAvatarFrame(member.getAvatarFrame())
                    //背景图
                    .setMemberBgPic(member.getMemberBackgroundUrl());
            userDetail.setMemberNo(member.getMemberNo()).setAvatarFrame(member.getAvatarFrame());
            if (convertBO.getNeedHideMemberLevel()) {
                userDetail.setMemberLevelPic(displayIcon.getMemberLevelPicPlaceHolder());
            } else {
                //不需要隐藏的时候才赋值
                userDetail.setMemberLevelPic(member.getMemberLevelPic());
            }
        }

        //运营标签
        LabelInfoPO businessLabel = convertBO.getBusinessLabel();
        if (Objects.nonNull(businessLabel)) {
            userDetail.setBusinessLabelDetail(new LabelInfoVO(businessLabel.getLabelName(), businessLabel.getLabelIcon()));
        }

        //实人、企业认证
        HeroUserAuthentication userAuthentication = convertBO.getUserAuthentication();
        if (Objects.nonNull(userAuthentication)) {
            userDetail.setRealPersonCertified(NumConsts.ONE.equals(userAuthentication.getIsRealNameAuth()))
                    .setRealName(userAuthentication.getRealName())
                    .setEnterpriseCertified(NumConsts.ONE.equals(userAuthentication.getIsEnterpriseAuth()))
                    .setEnterpriseName(userAuthentication.getEnterpriseName());
        }

        //公司职位
        userDetail.setCompanyPosition(userInfo.getCompanyPosition());
        //所在地区
        userDetail.setRegion(UserInfoConvert.parseRegion(userContact));

        //主营品类
        List<LabelInfoPO> managementLabels = convertBO.getManagementLabels();
        userDetail.setMainProductCates(this.buildMainProductCates(managementLabels, convertBO.getAllManagementLabelInfos()));

        //优势介绍
        userDetail.setAdvantagesIntroduction(this.buildAdvantagesIntroduction(convertBO.getAdvantagesLabels(), convertBO.getAllAdvantagesLabelInfos()));

        //平台认证标签
        userDetail.setPlatformCertifiedLabels(this.buildPlatformCertifiedLabels(userAuthentication, displayIcon));

        //个人简介
        userDetail.setPersonalDescription(userInfo.getPersonalIntroduction())
                //运营审核的身份
                .setCertifiedIdenties(this.buildCertifiedIdenties(uid, userAuthentication))
                //服务能力
                .setServiceabilities(this.buildServiceabilities(managementLabels))
                //近期动态
                .setRecentUpdates(convertBO.getUserRecents());

        //关系等级
        UserAttentionBO userAttentionBO = convertBO.getUserAttentionBO();
        if (Objects.nonNull(userAttentionBO)) {
            userDetail.setAttentionRelationCode(userAttentionBO.getAttentionRelationCode())
                    .setAttentionRelationDesc(userDetail.getAttentionRelationDesc());
        }

        //手机号
        userDetail.setContactMobile(userContact.getContactMobile());
        //认证标签,滚动展示
        userDetail.setFraternityAuthLabels(convertBO.getFraternityAuthLabels());
        //分组
        userDetail.setGroupNameList(convertBO.getGroupLabels());

        userDetail.setIsPublicContact(userContact.getIsPublicContact());
        userDetail.setIsRequireAttention(userContact.getIsRequireAttention());

        //统计数
        userDetail.setUserRecords(this.buildUserRecords(convertBO.getFollwedNum(), convertBO.getFansProfilePhotos(),
                convertBO.getCertifiedReliableNum(), convertBO.getDealSuccessOrderNum()));

        return userDetail;
    }

    private List<UserDetailVO.UserCountInfo> buildUserRecords(Long follwedNum, List<String> fansProfilePhotos,
                                                              Long certifiedReliableNum, Long dealSuccessOrderNum) {
        List<UserDetailVO.UserCountInfo> countList = new ArrayList<>();
        //粉丝数
        countList.add(new UserDetailVO.UserCountInfo().setType(NumConsts.ONE).setStrValue(StringUtil.convertNum(follwedNum)));

        //xxx也关注ta
        countList.add(new UserDetailVO.UserCountInfo().setType(NumConsts.TWO).setPhotoList(fansProfilePhotos));

        //靠谱值
        countList.add(new UserDetailVO.UserCountInfo().setType(NumConsts.THREE).setStrValue(StringUtil.convertNum(certifiedReliableNum)));

        //交易订单数
        countList.add(new UserDetailVO.UserCountInfo().setType(NumConsts.FOUR).setStrValue(StringUtil.convertNum(dealSuccessOrderNum)));

        return countList;
    }

    /**
     * 装配基本信息
     *
     * @param userInfo
     * @param userContact
     * @param memberDTO
     * @param labelInfoPO
     * @param fields      需要的字段
     * @param userComment
     * @param allField    如果为true则不看fields
     * @return com.zhuanzhuan.hero.user.vo.UserBaseInfoVO
     * @author hanjunjun
     * @date 2024/7/9
     **/
    private UserBaseInfoVO convertUserBaseInfo(HeroUserInfo userInfo, HeroUserContact userContact, MemberDTO memberDTO,
        LabelInfoPO labelInfoPO, List<String> fields, String userComment, boolean allField,
        String defaultProfilePhoto, HeroUserAuthentication userAuthentication, DisplayIconBO displayIcon,
        UserAttentionBO userAttentionBO) {
        UserBaseInfoVO vo = new UserBaseInfoVO();
        Long uid = userInfo.getUid();
        vo.setUid(uid)
                .setNickname(userInfoConvert.getNicknameWithUnregist(userInfo))
                .setOuterNickname(userInfoConvert.getOuterNicknameWithUnregist(userInfo, userContact))
                .setProfilePhoto(userInfoConvert.getProfilePhotoWithUnregist(userInfo, defaultProfilePhoto))
                .setOuterProfilePhoto(userInfoConvert.getOuterProfilePhotoWithUnregist(userInfo, userContact, defaultProfilePhoto))
                .setDefaultProfilePhoto(defaultProfilePhoto);
        if (allField || fields.contains(UserInfoFieldConsts.SEX_CODE)) {
            vo.setSexCode(userInfo.getSex()).setSexName(UserSexEnum.getNameByCode(userInfo.getSex()));
        }
        if (allField || fields.contains(UserInfoFieldConsts.COMPANY_POSITION)) {
            vo.setCompanyPosition(userInfo.getCompanyPosition());
        }

        if (allField || fields.contains(UserInfoFieldConsts.MEMBER_LEVEL)) {
            if (Objects.isNull(memberDTO)) {
                log.info("没有会员信息,不是会员");
                vo.setIsMember(NumConsts.ZERO);
            } else {
                vo.setIsMember(heroMemberHelper.isMember(memberDTO) ? NumConsts.ONE : NumConsts.ZERO)
                        .setMemberLevel(memberDTO.getMemberLevel())
                        .setMemberLevelName(memberDTO.getMemberLevelName())
                        .setAvatarFrame(memberDTO.getAvatarFrame())
                        .setMemberStatus(memberDTO.getMemberStatus())
                        .setFirstActivateTime(memberDTO.getFirstActivateTime())
                        .setMemberLevelPic(memberDTO.getMemberLevelPic());
            }
        }
        if (allField || fields.contains(UserInfoFieldConsts.BUSINESS_LABEL)) {
            if (Objects.nonNull(labelInfoPO)) {
                vo.setBusinessLabel(labelInfoPO.getLabelName());
            }
        }
        //备注
        if (allField || fields.contains(UserInfoFieldConsts.USER_COMMENTS)) {
            vo.setUserComments(userInfoConvert.getUserCommentsWithUnregist(userInfo, userComment));
        }
        if (allField || fields.contains(UserInfoFieldConsts.REGIST_MOBILE)) {
            vo.setRegistMobile(userInfo.getMobile());
        }
        if (allField || fields.contains(UserInfoFieldConsts.CONTACT_MOBILE)) {
            vo.setContactMobile(userContact.getContactMobile());
        }
        if (allField || fields.contains(UserInfoFieldConsts.WECAHT_NO)) {
            vo.setWechatNumber(userContact.getWechatNum());
        }
        if (allField || fields.contains(UserInfoFieldConsts.DOUYIN_NICKNAME)) {
            vo.setDouyinNickname(userContact.getDouyinNickname());
        }
        vo.setUserState(userInfo.getUserState());
        if (allField || fields.contains(UserInfoFieldConsts.REGION)) {
            vo.setRegion(UserInfoConvert.parseRegion(userContact));
        }
        if (allField || fields.contains(UserInfoFieldConsts.PLATFORM_CERTIFIED_LABELS)) {
            if (Objects.nonNull(userAuthentication)) {
                vo.setPlatformCertifiedLabels(this.buildPlatformCertifiedLabels(userAuthentication, displayIcon));
            }
        }
        if (allField || fields.contains(UserInfoFieldConsts.ATTENTION_RELEATION_CODE)) {
            if (Objects.nonNull(userAttentionBO)) {
                vo.setAttentionRelationCode(userAttentionBO.getAttentionRelationCode());
                vo.setAttentionRelationDesc(userAttentionBO.getAttentionRelationName());
            }
        }

        return vo;
    }

    /**
     * 靠谱按钮
     *
     * @param loginUid
     * @param homemakerUid
     * @return com.zhuanzhuan.hero.user.vo.UserDetailVO.ReliableBtn
     * @author hanjunjun
     * @date 2024/7/9
     **/
    private UserDetailVO.ReliableBtn buildReliableBtn(Long loginUid, Long homemakerUid) {
        UserDetailVO.ReliableBtn reliableBtn = new UserDetailVO.ReliableBtn();
        //查询认证记录
        List<HeroUserReliableRecord> authRecords =
                reliableRecordService.queryByParam(loginUid, homemakerUid, null, ReliableOperateTypeEnum.AUTH.getCode());
        if (CollectionUtils.isEmpty(authRecords)) {
            //还没有认证过
            reliableBtn.setBtnCode(ReliableBtnEnum.WAIT_CERTIFY.getCode());
            reliableBtn.setBtnName(ReliableBtnEnum.WAIT_CERTIFY.getName());
            reliableBtn.setIsCertified(NumConsts.ZERO);
            return reliableBtn;
        }

        //认证过靠谱
        boolean existAuthReliableRecord = authRecords.stream()
                .anyMatch(record -> ReliableAuthTypeEnum.RELIABLE.getCode().equals(record.getReliableType()));
        if (existAuthReliableRecord) {
            reliableBtn.setBtnCode(ReliableBtnEnum.CANCEL_RELIABLE.getCode());
            reliableBtn.setBtnName(ReliableBtnEnum.CANCEL_RELIABLE.getName());
            reliableBtn.setIsCertified(NumConsts.ONE);
            return reliableBtn;
        }

        //认证过不靠谱
        boolean existAuthUnReliableRecord = authRecords.stream()
                .anyMatch(record -> ReliableAuthTypeEnum.UNRELIABLE.getCode().equals(record.getReliableType()));
        if (existAuthUnReliableRecord) {
            reliableBtn.setBtnCode(ReliableBtnEnum.CANCEL_UNRELIABLE.getCode());
            reliableBtn.setBtnName(ReliableBtnEnum.CANCEL_UNRELIABLE.getName());
            reliableBtn.setIsCertified(NumConsts.ONE);
            return reliableBtn;
        }

        return reliableBtn;
    }

    private List<UserDetailVO.ContactInformationVO> buildContactInformations(ContactVisibleBO contactVisibleBO,
                                                                             HeroUserContact userContact, DisplayIconBO displayIconBO, Integer memberLevel) {
        List<UserDetailVO.ContactInformationVO> voList = new ArrayList<>();

        //手机号
        if (StringUtils.isNotBlank(userContact.getContactMobile())) {
            UserDetailVO.ContactInformationVO contactVO = new UserDetailVO.ContactInformationVO(ContactTypeEnum.MOBILE.getCode(),
                    DisplayIconBO.matchIconByMemberLevel(memberLevel, displayIconBO.getContactMobile()),
                    ContactTypeEnum.MOBILE.getName());
            if (contactVisibleBO.getIsVisible()) {
                contactVO.setStrValue(userContact.getContactMobile());
            }
            voList.add(contactVO);
        }
        //微信号
        if (StringUtils.isNotBlank(userContact.getWechatNum())) {
            UserDetailVO.ContactInformationVO contactVO = new UserDetailVO.ContactInformationVO(ContactTypeEnum.WECHAT_NUM.getCode(),
                    DisplayIconBO.matchIconByMemberLevel(memberLevel, displayIconBO.getContactWechat()), ContactTypeEnum.WECHAT_NUM.getName());
            if (contactVisibleBO.getIsVisible()) {
                contactVO.setStrValue(userContact.getWechatNum());
            }
            voList.add(contactVO);
        }
        //微信群
        if (StringUtils.isNotBlank(userContact.getWechatGroupCode())
                || StringUtils.isNotBlank(userContact.getWechatGroupName())
                || StringUtils.isNotBlank(userContact.getWechatGroupDesc())) {
            UserDetailVO.ContactInformationVO contactVO = new UserDetailVO.ContactInformationVO(ContactTypeEnum.WECHAT_GROUP.getCode(),
                    DisplayIconBO.matchIconByMemberLevel(memberLevel, displayIconBO.getContactWechatGroup()),
                    ContactTypeEnum.WECHAT_GROUP.getName());
            if (contactVisibleBO.getIsVisible()) {
                contactVO.setExtendValue(new UserDetailVO.ContactExtentValue(userContact.getWechatGroupCode(),
                        userContact.getWechatGroupName(), userContact.getWechatGroupDesc()));
            }
            voList.add(contactVO);
        }
        //抖音昵称
        if (StringUtils.isNotBlank(userContact.getDouyinNickname())) {
            UserDetailVO.ContactInformationVO contactVO = new UserDetailVO.ContactInformationVO(ContactTypeEnum.DOUYIN.getCode(),
                    DisplayIconBO.matchIconByMemberLevel(memberLevel, displayIconBO.getContactDouyin()), ContactTypeEnum.DOUYIN.getName());
            if (contactVisibleBO.getIsVisible()) {
                contactVO.setStrValue(userContact.getDouyinNickname());
            }
            voList.add(contactVO);
        }

        //如果不可见 设置不可点击和文案
        if (!contactVisibleBO.getIsVisible()) {
            voList.forEach(contactVO -> {
                contactVO.setCanClick(false);
                contactVO.setTips(contactVisibleBO.getTips());
            });
        }

        return voList;
    }

    /**
     * 判断联系方式是否可见
     *
     * @param loginUid
     * @param homemakerUid
     * @param heroUserContact
     * @return com.zhuanzhuan.hero.user.pojo.bo.ContactVisibleBO
     * @author hanjunjun
     * @date 2024/7/9
     **/
    private ContactVisibleBO contactVisible(Long loginUid, Long homemakerUid, HeroUserContact heroUserContact) {
        Integer isPublicContact = heroUserContact.getIsPublicContact();
        if (NumConsts.ONE.equals(isPublicContact)) {
            return ContactVisibleBO.visible();
        }

        //是否关注后可见
        Integer isAttentionVisible = heroUserContact.getIsRequireAttention();
        if (!NumConsts.ONE.equals(isAttentionVisible)) {
            return ContactVisibleBO.unVisible("该用户设置了联系方式不可见，直接跟他聊聊吧");
        }

        //是否关注
        boolean isAttention = attentionService.isAttention(loginUid, homemakerUid);
        if (isAttention) {
            return ContactVisibleBO.visible();
        }
        return ContactVisibleBO.unVisible("该用户开启了关系限制，关注后即可查看联系方式");
    }

    /**
     * 判断用户信息是否完善完成
     *
     * @param userInfo
     * @param userContact
     * @param managementLabelInfos 关联的经营标签
     * @return com.zhuanzhuan.hero.user.vo.UserDetailVO.PersonInfoPerfectionVO
     * @author hanjunjun
     * @date 2024/7/9
     **/
    private UserDetailVO.PersonInfoPerfectionVO buildPersonInfoPerfectDegree(HeroUserInfo userInfo,
                                                                             HeroUserContact userContact, List<LabelInfoPO> managementLabelInfos) {
        if (this.personInfoPerfection(userInfo.getUid(), userInfo, userContact, managementLabelInfos)) {
            return UserDetailVO.PersonInfoPerfectionVO.success();
        }

        return UserDetailVO.PersonInfoPerfectionVO.fail();
    }

    /**
     * 功能区按钮
     *
     * @param userInfo
     * @param displayIcon
     * @param memberLevel 会员等级
     * @return java.util.List<com.zhuanzhuan.hero.user.vo.UserDetailVO.FunctionalDomainItem>
     * @author hanjunjun
     * @date 2024/7/8
     **/
    private List<UserDetailVO.FunctionalDomainItem> buildFunctionalDomain(HeroUserInfo userInfo, DisplayIconBO displayIcon,
                                                                          Integer memberLevel, PageUrlBO pageUrlBO, boolean isOther, boolean isShowVisitor) {
        List<UserDetailVO.FunctionalDomainItem> voList = new ArrayList<>();
        //客态没有功能区
        if (isOther) {
            return voList;
        }

        //我的回收单、我卖的   主态时才展示
        //查询进行送检卖出的订单列表
        UserCenterSellAndRecycleCountVO userCenterSellAndRecycleCount =
                heroRecycleOrderHelper.querySellAndRecycleCount(userInfo.getUid());
        if (Objects.nonNull(userCenterSellAndRecycleCount)) {
            voList.add(new UserDetailVO.FunctionalDomainItem(NumConsts.ONE,
                    DisplayIconBO.matchIconByMemberLevel(memberLevel, displayIcon.getMyRecycleOrder()),
                    UserInfoConvert.buildMyRecycleOrderTab(userCenterSellAndRecycleCount.getRecycleCount()),
                    pageUrlBO.getMyRecycleOrder()));
            voList.add(new UserDetailVO.FunctionalDomainItem(NumConsts.TWO,
                    DisplayIconBO.matchIconByMemberLevel(memberLevel, displayIcon.getMySell()),
                    UserInfoConvert.buildMySellTab(userCenterSellAndRecycleCount.getSellCount()),
                    pageUrlBO.getMySell()));
        }

        //访客记录,主客态都展示
        if (isShowVisitor) {
            voList.add(new UserDetailVO.FunctionalDomainItem(NumConsts.THREE,
                    DisplayIconBO.matchIconByMemberLevel(memberLevel, displayIcon.getVisitRecord()), "访客记录",
                    String.format(pageUrlBO.getVisitRecords(), userInfo.getUid())));
        }

        return voList;
    }

    /**
     * 邀请官信息
     *
     * @param recommenderId
     * @return com.zhuanzhuan.hero.user.vo.UserBriefInfoVO
     * @author hanjunjun
     * @date 2024/7/8
     **/
    private UserBriefInfoVO buildInviter(Long recommenderId) {
        if (Objects.isNull(recommenderId)) {
            return null;
        }

        HeroUserInfo recommender = userInfoService.getUserByUid(recommenderId);
        if (Objects.isNull(recommender)) {
            log.info("邀请官不存在 uid={}", recommender);
            return null;
        }
        UserBriefInfoVO vo = new UserBriefInfoVO();
        vo.setUid(recommenderId);
        vo.setNickname(recommender.getNickname());
        vo.setProfilePhoto(recommender.getProfilePhoto());

        MemberDTO member = heroMemberHelper.queryMember(recommenderId);
        if (!heroMemberHelper.isMember(member)) {
            log.error("推荐官不是会员, uid={}", recommenderId);
            throw new BusinessException(ExceptionMsgEnum.BUSINESS_ERROR.getCode(), "推荐官不是会员");
        }
        vo.setMemberLevel(member.getMemberLevel());

        return vo;
    }

    /**
     * 服务能力标签
     *
     * @param managementLabelInfos
     * @return java.util.List<java.lang.String>
     * @author hanjunjun
     * @date 2024/7/8
     **/
    private List<String> buildServiceabilities(List<LabelInfoPO> managementLabelInfos) {
        if (CollectionUtils.isEmpty(managementLabelInfos)) {
            return new ArrayList<>();
        }
        return managementLabelInfos.stream()
                .filter(label -> LabelCodeEnum.SERVICE_ABILITY.getCode().equals(label.getParentLabelCode()))
                .map(LabelInfoPO::getLabelName)
                .collect(Collectors.toList());
    }

    /**
     * 优势介绍
     *
     * @param relatedLabels 用户关联的标签
     * @param labelInfos    这种类型所有的标签  用于层级查找
     * @return java.util.List<java.lang.String>
     * @author hanjunjun
     * @date 2024/7/8
     **/
    private List<String> buildAdvantagesIntroduction(List<LabelInfoPO> relatedLabels, List<HeroLabelInfo> labelInfos) {
        List<String> resultList = new ArrayList<>();
        if (CollectionUtils.isEmpty(relatedLabels)) {
            return new ArrayList<>();
        }

        if (CollectionUtils.isEmpty(labelInfos)) {
            labelInfos = labelInfoService.listByParam(LabelInfoQueryBO.builder().labelType(LabelTypeEnum.ADVANTAGE.getCode()).build());
        }

        /*List<HeroLabelInfo> labelInfos = labelInfoService.listByParam(
            LabelInfoQueryBO.builder().labelType(LabelTypeEnum.ADVANTAGE.getCode()).build());*/
        //K:一级标签名 v：三级标签名
        MultiValueMap<String, String> firstThirdLabelMap = new LinkedMultiValueMap<>();
        //------------拼接成"货类-小花 大花 外爆"的格式-----------------
        //k:一级标签的showOrder   v:一级标签的名称
        TreeMap<Integer, String> labelOrderMap = new TreeMap<>();
        List<HeroLabelInfo> finalLabelInfos = labelInfos;
        relatedLabels.forEach(relatedLabel -> {
            //根据三级找一级
            HeroLabelInfo firstLevelLabel =
                    LabelConverter.findTopLevelByLastLevel(relatedLabel.getLabelId(), finalLabelInfos);
            if (Objects.nonNull(firstLevelLabel)) {
                //"优势品牌"处理成"品牌"
                String firstLevelLabelName = UserInfoConvert.convertAdvantageShowName(firstLevelLabel.getLabelName());
                labelOrderMap.put(firstLevelLabel.getShowOrder(), firstLevelLabelName);
                firstThirdLabelMap.add(firstLevelLabelName, relatedLabel.getLabelName());
            }
        });

        if (MapUtils.isNotEmpty(labelOrderMap)) {
            labelOrderMap.forEach((labelShowOrder, firstLabelName) -> {
                List<String> thirdLabelNames = firstThirdLabelMap.get(firstLabelName);
                if (CollectionUtils.isNotEmpty(thirdLabelNames)) {
                    //[一级标签]-[三级标签]
                    resultList.add(firstLabelName + Consts.LABEL_CODE_SPLIT + String.join(" ", thirdLabelNames));
                }
            });
        }

        return resultList;
    }

    private List<UserDetailVO.CertifiedIdentieVO> buildCertifiedIdenties(Long uid, HeroUserAuthentication userAuthentication) {
        List<UserDetailVO.CertifiedIdentieVO> voList = new ArrayList<>();
        //一期不展示审核图片
        if (NumConsts.ONE.equals(userAuthentication.getIsStoreAuth())) {
            voList.add(new UserDetailVO.CertifiedIdentieVO(UserAuthTypeEnum.STORE.getName()));
        }
        if (NumConsts.ONE.equals(userAuthentication.getIsRecyclerAuth())) {
            voList.add(new UserDetailVO.CertifiedIdentieVO(UserAuthTypeEnum.RECYCER.getName()));
        }
        if (NumConsts.ONE.equals(userAuthentication.getIsEMerchantAuth())) {
            voList.add(new UserDetailVO.CertifiedIdentieVO(UserAuthTypeEnum.E_MERCHANT.getName()));
        }
        if (NumConsts.ONE.equals(userAuthentication.getIsLargeGoodsAuth())) {
            voList.add(new UserDetailVO.CertifiedIdentieVO(UserAuthTypeEnum.LARGE_GOODS.getName()));
        }
        if (NumConsts.ONE.equals(userAuthentication.getIsDouyinTalent())) {
            voList.add(new UserDetailVO.CertifiedIdentieVO(UserAuthTypeEnum.DOUYIN_TALENT.getName()));
        }

        return voList;
    }

    /**
     * 已认证的平台标签
     * 抖音大v、已验机2.0、保卖仓
     *
     * @param userAuthentication
     * @return java.util.List<com.zhuanzhuan.hero.user.vo.label.PaltformAuthLabelVO>
     * @author hanjunjun
     * @date 2024/7/8
     **/
    private List<PaltformAuthLabelVO> buildPlatformCertifiedLabels(HeroUserAuthentication userAuthentication,
                                                                   DisplayIconBO displayIcon) {
        List<PaltformAuthLabelVO> voList = new ArrayList<>();

        if (NumConsts.ONE.equals(userAuthentication.getIsDouyinVAuth())) {
            voList.add(new PaltformAuthLabelVO("抖音粉" + userAuthentication.getDouyinVLabel(),
                    displayIcon.getDouyinV()));
        }
        if (NumConsts.ONE.equals(userAuthentication.getIsZhuanzhuanMerchantAuth())) {
            voList.add(new PaltformAuthLabelVO(UserAuthTypeEnum.ZHUANZHUAN_MERCHANT.getName(),
                    displayIcon.getZhuanzhuanMerchant()));
        }
        if (NumConsts.ONE.equals(userAuthentication.getIsBmWarehouseAuth())) {
            voList.add(new PaltformAuthLabelVO(UserAuthTypeEnum.BM_WAREHOUSE.getName(), displayIcon.getBmWareHouse()));
        }

        return voList;
    }

    /**
     * 主营品类的名称
     *
     * @param managementlabelInfos
     * @return java.util.List<java.lang.String>
     * @author hanjunjun
     * @date 2024/7/8
     **/
    private List<String> buildMainProductCates(List<LabelInfoPO> managementlabelInfos, List<HeroLabelInfo> allManagementLabelInfos) {
        if (CollectionUtils.isEmpty(allManagementLabelInfos)) {
            LabelInfoQueryBO queryBO = LabelInfoQueryBO.builder().labelType(LabelTypeEnum.MANAGEMENT.getCode()).build();
            allManagementLabelInfos = labelInfoService.listByParam(queryBO);
        }
        return LabelConverter.findBusinessCateChilds(managementlabelInfos, allManagementLabelInfos).stream()
                .map(LabelInfoPO::getLabelName)
                .collect(Collectors.toList());
    }

    /**
     * 查询用户的被认证数
     * 粉丝数、xxx也关注了、靠谱值、交易订单数
     *
     * @param homemakerUid
     * @return java.util.List<com.zhuanzhuan.hero.user.vo.UserDetailVO.UserCountInfo>
     * @author hanjunjun
     * @date 2024/7/8
     **/
    private List<UserDetailVO.UserCountInfo> queryUserCertifedNums(Long loginUid, Long homemakerUid, boolean isOther,
                                                                   PageUrlBO pageUrlBO) {
        List<UserDetailVO.UserCountInfo> countList = new ArrayList<>();
        //粉丝数
        Long follwedNums = counterService.queryFollowedNum(homemakerUid);
        countList.add(new UserDetailVO.UserCountInfo(NumConsts.ONE, "同行关注", StringUtil.convertNum(follwedNums),
                String.format(pageUrlBO.getFansList(), homemakerUid)));

        //xxx也关注ta  客态才有值
        if (isOther) {
            List<String> profilePhotos = heroSocialHelper.queryContactList(loginUid, homemakerUid);
            if (CollectionUtils.isNotEmpty(profilePhotos)) {
                countList.add(new UserDetailVO.UserCountInfo(NumConsts.TWO, "也关注了他", profilePhotos,
                    String.format(pageUrlBO.getFansList(), homemakerUid)));
            }
        }

        //靠谱值
        Long certifiedReliableNum = counterService.queryCertifiedReliableNum(homemakerUid);
        countList.add(new UserDetailVO.UserCountInfo(NumConsts.THREE, "靠谱",
                StringUtil.convertNum(certifiedReliableNum), String.format(pageUrlBO.getReliableList(), homemakerUid)));

        //交易订单数
        Long dealSuccessOrderNum = counterService.queryDealSuccessRecycleOrderNum(homemakerUid);
        countList.add(new UserDetailVO.UserCountInfo(NumConsts.FOUR, "交易数",
                StringUtil.convertNum(dealSuccessOrderNum)));

        return countList;
    }

    /**
     * 赋值头像昵称   判断是展示端内的还是端外的
     *
     * @param userDetailVO
     * @param userInfo
     * @param userContact
     * @param isOuter      是否是端外
     * @param isOther      是否是客态  端内且客态的昵称展示备注
     * @param loginUid     用于查备注
     * @return void
     * @author hanjunjun
     * @date 2024/7/6
     **/
    private void buildNicknameProfilePhoto(UserDetailVO userDetailVO, HeroUserInfo userInfo, HeroUserContact userContact,
                                           boolean isOuter, boolean isOther, Long loginUid) {
        //如果是端外，展示端外的头像昵称   否则就展示端内的
        if (isOuter) {
            //用户可能直接扫回收商的报价单码进入小程序，如果回收商没设置过端外头像昵称的话是没有的   这里兼容下，赋值端内的头像昵称
            String outerNickname = userContact.getOuterNickname();
            userDetailVO.setNickname(StringUtils.isNotBlank(outerNickname) ? outerNickname : userInfo.getNickname());
            String outerProfilePhoto = userContact.getOuterProfilePhoto();
            userDetailVO.setProfilePhoto(StringUtils.isNotBlank(outerProfilePhoto) ? outerProfilePhoto : userInfo.getProfilePhoto());
        } else {
            //如果是客态  查询备注
            if (isOther) {
                String notes = userNotesService.queryNotesByUid(loginUid, userInfo.getUid());
                userDetailVO.setNickname(StringUtils.isNotBlank(notes) ? notes : userInfo.getNickname());
            } else {
                userDetailVO.setNickname(userInfo.getNickname());
            }
            userDetailVO.setProfilePhoto(userInfo.getProfilePhoto());
        }
    }

    private UserBriefInfoVO convertUserBriefInfoVO(UserBaseInfoVO userBaseInfoVO) {
        if (userBaseInfoVO == null) {
            return null;
        }
        UserBriefInfoVO userBriefInfoVO = new UserBriefInfoVO();
        userBriefInfoVO.setUid(userBaseInfoVO.getUid());
        userBriefInfoVO.setNickname(userBaseInfoVO.getOuterNickname());
        userBriefInfoVO.setProfilePhoto(userBaseInfoVO.getOuterProfilePhoto());
        return userBriefInfoVO;
    }

    private UserItemBriefVO convertUserItem(Long otherUid, Map<Long, HeroUserInfo> otherUserInfoMap,
                                            Map<Long, String> otherUserNotesMap, Map<Long, UserAttentionBO> otherUserAttentionMap,
                                            Map<Long, MemberDTO> uidMemberMap) {
        HeroUserInfo userInfo = otherUserInfoMap.get(otherUid);
        if (Objects.isNull(userInfo)) {
            throw new BusinessException(ExceptionMsgEnum.BUSINESS_ERROR);
        }

        UserItemBriefVO vo = new UserItemBriefVO();
        String displayNickname = StringUtils.isNotBlank(otherUserNotesMap.get(otherUid)) ? otherUserNotesMap.get(otherUid)
                : userInfo.getNickname();

        vo.setUid(otherUid)
                .setHeadImgUrl(userInfoConvert.getProfilePhotoWithUnregist(userInfo, StringUtils.EMPTY))
                .setNickName(userInfoConvert.getNicknameWithUnregist(userInfo, displayNickname))
                .setUserRemark(userInfo.getPersonalIntroduction());
        //是否已注销
        boolean isCancelAccount = userInfo.isUnregistered();
        vo.setIsCancelAccount(isCancelAccount);
        if (isCancelAccount) {
            log.info("用户{}已注销，不赋值多余字段", otherUid);
            return vo;
        }

        Optional.ofNullable(uidMemberMap.get(otherUid))
                .ifPresent(member -> {
                    vo.setIsMember(heroMemberHelper.isMember(member))
                            .setMemberType(member.getMemberLevel())
                            .setMemberTypeDesc(member.getMemberLevelName())
                            .setMemberLevelPic(member.getMemberLevelPic())
                            .setAvatarFrame(member.getAvatarFrame());
                });

        //关系类型
        UserAttentionBO userAttention = otherUserAttentionMap.get(otherUid);
        if (Objects.nonNull(userAttention)) {
            vo.setAttentionRelationCode(userAttention.getAttentionRelationCode())
                    .setAttentionRelationDesc(userAttention.getAttentionRelationName());
        }

        return vo;
    }

    /**
     * 根据入参传递的字段选择性地查询对应字段
     *
     * @param uid
     * @param fields
     * @return com.zhaunzhuan.hero.user.vo.UserBaseInfoVO
     * @author hanjunjun
     * @date 2024/6/20
     **/
    private UserBaseInfoVO selectiveQueryUserBaseInfo(Long uid, List<String> fields) {
        log.info("queryUserBaseInfoSelective uid={}, fields={}", uid, fields);
        fields = fields.stream().distinct().collect(Collectors.toList());
        HeroUserInfo heroUserInfo = userInfoService.getUserByUid(uid);
        if (Objects.isNull(heroUserInfo)) {
            return null;
        }

        UserBaseInfoVO vo = new UserDetailVO();
        vo.setUid(heroUserInfo.getUid())
                .setNickname(heroUserInfo.getNickname())
                .setProfilePhoto(heroUserInfo.getProfilePhoto());

        if (fields.contains(UserInfoFieldConsts.SEX_CODE)) {
            vo.setSexCode(heroUserInfo.getSex());
        }
        if (fields.contains(UserInfoFieldConsts.SEX_NAME)) {
            vo.setSexName(UserSexEnum.getNameByCode(heroUserInfo.getSex()));
        }
        if (fields.contains(UserInfoFieldConsts.COMPANY_POSITION)) {
            vo.setCompanyPosition(heroUserInfo.getCompanyPosition());
        }

        if (fields.contains(UserInfoFieldConsts.MEMBER_LEVEL)) {
            Optional.ofNullable(heroMemberHelper.queryMember(uid)).ifPresent(member -> {
                vo.setMemberLevel(member.getMemberLevel())
                        .setMemberLevelName(member.getMemberLevelName());
            });
        }

        //运营标签
        if (fields.contains(UserInfoFieldConsts.BUSINESS_LABEL)) {
            List<LabelInfoPO> businessLabels =
                    labelRelationService.queryUserRealateLabelInfos(Collections.singletonList(uid), LabelTypeEnum.BUSINESS.getCode());
            if (CollectionUtils.isNotEmpty(businessLabels)) {
                LabelInfoPO businessLabelInfo = businessLabels.get(NumConsts.ZERO);
                vo.setBusinessLabel(businessLabelInfo.getLabelName());
            }
        }

        if (fields.contains(UserInfoFieldConsts.REGIST_MOBILE)) {
            vo.setRegistMobile(heroUserInfo.getMobile());
        }

        HeroUserContact heroUserContact = userContactService.getByUid(uid);
        if (fields.contains(UserInfoFieldConsts.OUTER_NICKNAME)) {
            vo.setOuterNickname(heroUserContact.getOuterNickname());
        }
        if (fields.contains(UserInfoFieldConsts.OUTER_PROFILE_PHOTO)) {
            vo.setOuterProfilePhoto(heroUserContact.getOuterProfilePhoto());
        }
        if (fields.contains(UserInfoFieldConsts.CONTACT_MOBILE)) {
            vo.setContactMobile(heroUserContact.getContactMobile());
        }

        return vo;
    }

    private HeroUserInfo buildRegisterUserInfo(Long uid, String mobile) {
        HeroUserInfo heroUserInfo = new HeroUserInfo();
        UserInfoDefaultBO userInfoDefaultBO = apolloService.queryDefauleProperties();
        heroUserInfo.setUid(uid)
                .setMobile(mobile)
                .setNickname(this.initNickname(mobile))
                .setProfilePhoto(userInfoDefaultBO.getDefaultProfilePhoto())
                .setLastEffectiveProfilePhoto(userInfoDefaultBO.getDefaultProfilePhoto())
                .setUserState(UserStateEnum.WAIT_SETTLE.getCode())
                .setBackdrop(userInfoDefaultBO.getDefaultBackdrop())
                .setIsShowVisitor(NumConsts.ONE)
                .setIsOpenPersonalRecommend(NumConsts.ONE)
                .setState(StateEnum.EFFECTIVE.getCode())
                .setCreateBy(NumConsts.SYSTEM_CODE)
                .setUpdateBy(NumConsts.SYSTEM_CODE);
        return heroUserInfo;
    }

    private String initNickname(String mobile) {
        return "侠客汇_" + mobile.substring(mobile.length() - 4);
    }

    private void buildUserAuthenticationDetail(UserDetailVO userDetailVO, HeroUserAuthentication userAuthentication) {
        userDetailVO.setRealPersonCertified(NumConsts.ONE.equals(userAuthentication.getIsRealNameAuth()))
                .setRealName(userAuthentication.getRealName())
                .setEnterpriseCertified(NumConsts.ONE.equals(userAuthentication.getIsEnterpriseAuth()))
                .setEnterpriseName(userAuthentication.getEnterpriseName());
    }

    private Map<Long, UserAttentionBO> queryUserAttentionMap(Long fromUid, List<Long> toUids) {
        //查询关系等级
        List<UserAttentionBO> otherUserAttentions = heroSocialHelper.queryserAttentions(fromUid, toUids);
        //k:访问者的uid
        return otherUserAttentions.stream().collect(Collectors.toMap(UserAttentionBO::getToUid, Function.identity()));

    }

    private void checkAndWarnExceptionUser(String mobile, Long uid) {
        QueryUserInfoParam param = new QueryUserInfoParam();
        param.setRegistMobile(mobile);
        List<UserPO> users = userInfoService.listByParam(param);
        if (CollectionUtils.isEmpty(users)) {
            return;
        }
        UserPO existUser = users.get(NumConsts.ZERO);
        //如果是一个非注销的状态  属于异常情况，告警
        if (!UserStateEnum.UNREGISTERED.getCode().equals(existUser.getUserState())) {
            log.error("注册时手机号已存在一个和现有uid不一致且非注销的用户 mobile={},uid={}", mobile, uid);
            String errorMsgFormat = "注册时手机号已存在一个和现有uid不一致且非注销的用户,mobile=%s,uid=%s";
            WxWarnTemplateUtil.warnOutService(Consts.SERVICE_NAME, String.format(errorMsgFormat, mobile, uid));
        }
    }

}
